package javaNIO1.channel;

import java.io.*;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
 * Created with Intel IDEA.
 *
 *  使用映射文件和gathering写操作 来编写http 回复
 *
 * @Auther: gjt
 * @Date: 2024/7/14 15:38
 */
public class MappedHttp {

    private static final String OUT_PUT = "C:\\Users\\23152\\Desktop\\hello.txt";
    private static final String LINE_SPE = "\r\n";
    private static final String SERVER_ID = "152.136.138.218";
    private static final String HTTP_HDR = "HTTP/1.0 200 OK" + LINE_SPE + SERVER_ID + LINE_SPE;
    private static final String HTTP_404_HDR = "HTTP/1.0 400 Not Fount" + LINE_SPE + SERVER_ID + LINE_SPE;
    private static final String MSG_404 = "Not Found File :";

    public static void main(String[] args) throws IOException {
        if(args.length < 1){
            System.out.println("请输入文件名！");
            return;
        }
        String file = args[0];

        // 构建响应头缓冲区
        ByteBuffer headBuffer = ByteBuffer.wrap(bytes(HTTP_HDR));
        // 类似响应体缓冲区
        ByteBuffer dyndrs = ByteBuffer.allocate(128);
        // 使用gathering 写入
        ByteBuffer[] gather = {headBuffer, dyndrs, null};
        String contentType = "unknown/unknown";
        long contentLength = -1;
        try{
            FileInputStream inputStream = new FileInputStream(file);
            FileChannel channel = inputStream.getChannel();

            // 获取内存映射文件
            MappedByteBuffer mapBuffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

            // 将内存映射文件缓冲区方法  第三位
            gather[2] = mapBuffer;
            // 获取通道的长度 以及文件类型  即mime 类型
            contentLength = channel.size();
            contentType = URLConnection.guessContentTypeFromName(file);
        }catch (IOException e){
            // 文件没有被打开
            ByteBuffer allocate = ByteBuffer.allocate(128);
            String MSG = MSG_404 + e + LINE_SPE;
            allocate.put(bytes(MSG));

            // 翻转  position 为0； 上界为最后一个元素的下一个索引
            allocate.flip();
            // 使用 错误 http 响应
            gather[0] = ByteBuffer.wrap(bytes(HTTP_404_HDR));

            // 消息类似
            gather[2] = allocate;
            // 纯文本
            contentType = "text/plain";

            contentLength = MSG.length();
        }

        // 响应体里边的内容
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("Content-Length: " + contentLength);
        stringBuilder.append(LINE_SPE);
        stringBuilder.append("Content-Type: " + contentType);
        stringBuilder.append(LINE_SPE).append(LINE_SPE);

        // 响应体写入缓冲区
        dyndrs.put(bytes(stringBuilder.toString()));
        dyndrs.flip();


        FileOutputStream fileOutputStream = new FileOutputStream(OUT_PUT);
        FileChannel channel = fileOutputStream.getChannel();
        // gathering 写入所有缓冲区数据   到输出文件的文件通道
        while(channel.write(gather) > 0){

        }
        channel.close();
        System.out.println("写入到 " + OUT_PUT);
    }


    private static byte[] bytes(String string) throws UnsupportedEncodingException {
        return string.getBytes(string);
    }
}
